package cn.wolfcode.p2p.business.service.impl;

import java.math.BigDecimal;
import java.util.Date;

import cn.wolfcode.p2p.base.domain.Account;
import cn.wolfcode.p2p.base.domain.LoginInfo;

import cn.wolfcode.p2p.base.service.IAccountService;
import cn.wolfcode.p2p.business.domain.BidRequest;
import cn.wolfcode.p2p.business.domain.CreditTransfer;
import cn.wolfcode.p2p.business.domain.PaymentScheduleDetail;
import cn.wolfcode.p2p.business.mapper.CreditTransferMapper;
import cn.wolfcode.p2p.business.mapper.PaymentScheduleDetailMapper;
import cn.wolfcode.p2p.business.query.BidRequestAuditQueryObject;
import cn.wolfcode.p2p.business.query.CreditTransferQueryObject;
import cn.wolfcode.p2p.business.service.IAccountFlowService;
import cn.wolfcode.p2p.business.service.IBidRequestService;
import cn.wolfcode.p2p.business.service.ICreditTransferService;
import cn.wolfcode.p2p.business.service.IPaymentScheduleDetailService;
import cn.wolfcode.p2p.util.Assert;
import cn.wolfcode.p2p.util.Constants;
import cn.wolfcode.p2p.util.UserContext;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Transactional
@Service
public class CreditTransferServiceImpl implements ICreditTransferService {

    @Autowired
    private CreditTransferMapper creditTransferMapper;
    @Autowired
    private PaymentScheduleDetailMapper detailMapper;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IBidRequestService bidRequestService;
    @Autowired
    private IAccountFlowService accountFlowService;
    @Autowired
    private IPaymentScheduleDetailService paymentScheduleDetailService;

    @Override
    public PageInfo selectForPage(CreditTransferQueryObject qo) {
        PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
        List list = creditTransferMapper.listForPage(qo);
        return new PageInfo(list);
    }

    /**
     * 根据 bidId查询出当前用户的准备转让的债权标,设置相关值,插入到 CreditTransfer表中
     *
     * @param bidId
     */
    @Override
    public void creditTransfer(Long[] bidId) {

        LoginInfo loginInfo = UserContext.getLoginInfo();

        List<CreditTransfer> readyCreditTransfers = creditTransferMapper.listReadyCreditTransfers(bidId, loginInfo.getId());
        for (CreditTransfer transfer : readyCreditTransfers) {
            //手动设置的参数
            transfer.setBidRequestState(Constants.TRANSFER_STATE_BIDDING);
            transfer.setTransFrom(loginInfo);
            transfer.setPublishDate(new Date());
            //保存数据
            creditTransferMapper.insert(transfer);

            //把这个债权标下面的收款计划--转让状态 修改为转让中
            detailMapper.batchUpdateTransferStateByBidIdAndToLoginInfoId(transfer.getBidId(), loginInfo.getId(),
                    PaymentScheduleDetail.TRANSFER_STATE_TRANSFERRING);
        }

    }

    @Override
    public PageInfo queryForInvestPage(CreditTransferQueryObject qo) {
        PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
        List list = creditTransferMapper.selectForInvestPage(qo);
        return new PageInfo(list);
    }

    @Override
    public void subscribe(Long id) {
        //债权认购：判断
        //1.判断当前在转让标的状态要处于 招标中
        //转让标信息
        CreditTransfer creditTransfer = creditTransferMapper.selectByPrimaryKey(id);
        Assert.isFalse(creditTransfer.getBidRequestState() != Constants.TRANSFER_STATE_BIDDING, "当前状态不处于招标中");

        //2.判断当前用户不能是转让人
        //当前登录对象
        LoginInfo loginInfo = UserContext.getLoginInfo();
        Long transUserId = creditTransfer.getTransFrom().getId();
        System.out.println(transUserId);
        Assert.isFalse(loginInfo.getId().equals(transUserId), "转让人无权认购自己的债权标");

        //3.判断当前用户不能是借款人
        //借款对象
        BidRequest br = bidRequestService.getById(creditTransfer.getBidRequestId());
        Assert.isFalse(loginInfo.getId().equals(br.getCreateUser().getId()), "无权投自己的标");

        //4.判断认购人可用余额是否足够
        //认购人账户
        Account transferToAccount = accountService.getById(loginInfo.getId());
        Assert.isFalse(transferToAccount.getUsableAmount().compareTo(creditTransfer.getBidRequestAmount()) < 0, "可用余额不足,请充值再认购");

        //转让人
        //转让人账户
        Account transferFromAccount = accountService.getById(creditTransfer.getTransFrom().getId());
        //1.可用余额增加债权标本金
        transferFromAccount.addUsableAmount(creditTransfer.getBidRequestAmount());
        //2.创建转让成功流水
        accountFlowService.createTransferSuccessFlow(transferFromAccount, creditTransfer.getBidRequestAmount(), creditTransfer.getBidRequestTitle());
        //3.待收本金减少
        transferFromAccount.setUnReceivePrincipal(transferFromAccount.getUnReceivePrincipal().subtract(creditTransfer.getBidRequestAmount()));
        //4.待收利息减少
        transferFromAccount.setUnReceiveInterest(transferFromAccount.getUnReceiveInterest().subtract(creditTransfer.getRemainInterest()));
        accountService.update(transferFromAccount);

        //认购人
        //1.认购人可用余额减少
        transferToAccount.subtractUsableAmount(creditTransfer.getBidRequestAmount());
        //2.创建认购成功流水
        accountFlowService.createSubscribeSuccessFlow(transferToAccount, creditTransfer.getBidRequestAmount(), creditTransfer.getBidRequestTitle());
        //3.待收本金增加
        transferToAccount.setUnReceivePrincipal(transferToAccount.getUnReceivePrincipal().add(creditTransfer.getBidRequestAmount()));
        //4.待收利息增加
        transferToAccount.setUnReceiveInterest(transferToAccount.getUnReceiveInterest().add(creditTransfer.getRemainInterest()));
        accountService.update(transferToAccount);

        //其他
        //1.债权标的状态修改为已认购
        creditTransfer.setBidRequestState(Constants.TRANSFER_STATE_SUBSCRIPTION);
        //2.设置债权标的认购人
        creditTransfer.setTransTo(loginInfo);
        //3.设置债权标的认购时间
        creditTransfer.setTransDate(new Date());
        update(creditTransfer);

        //4.修改该债权标下的收款计划的转让状态为正常
        detailMapper.batchUpdateTransferStateByBidIdAndToLoginInfoId(creditTransfer.getBidId(), creditTransfer.getTransFrom().getId(), PaymentScheduleDetail.TRANSFER_STATE_NORMAL);

        //5.修改该债权标下的收款计划的收款人为 认购人
        detailMapper.batchUpdateToLoginInfoIdByBidIdAndTransferFromId(creditTransfer.getBidId(), creditTransfer.getTransFrom().getId(), loginInfo.getId());

    }

    @Override
    public CreditTransfer getByBidIdAndTransferFromIdAndState(Long bidId, Long toLoginInfoId, int transferStateBidding) {
        return creditTransferMapper.getByBidIdAndTransferFromIdAndState(bidId, toLoginInfoId, transferStateBidding);
    }

    @Override
    public void update(CreditTransfer creditTransfer) {
        Assert.isFalse(0 == creditTransferMapper.updateByPrimaryKey(creditTransfer), "更新操作失败,[乐观锁修改失败]");
    }

    @Override
    public PageInfo queryForTransferPage(CreditTransferQueryObject qo) {
        PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
        List list = creditTransferMapper.ListForTransferPage(qo);
        return new PageInfo(list);
    }

    @Override
    public void cancelCredit(Long id) {

        //获取转出对象
        CreditTransfer creditTransfer = creditTransferMapper.selectByPrimaryKey(id);
        //登录用户
        LoginInfo loginInfo = UserContext.getLoginInfo();
        //判断当前用户是否转出人
        Assert.isFalse(!creditTransfer.getTransFrom().getId().equals(loginInfo.getId()), "非发布债权用户,无权撤销");

        //获取所有的收款计划对象
        List<PaymentScheduleDetail> details = detailMapper.listAll(creditTransfer.getBidId());
        for (PaymentScheduleDetail detail : details) {
            //1.判断当前收款计划是否处于转让中
            if (detail.getTransferState() == PaymentScheduleDetail.TRANSFER_STATE_TRANSFERRING) {
                //2.根据这个收款计划查找到对应的债标
                creditTransferMapper.getByBidIdAndTransferFromIdAndState(detail.getBidId(), detail.getToLoginInfoId(), Constants.TRANSFER_STATE_BIDDING);

                //3.修改债权标的状态为撤销
                creditTransfer.setBidRequestState(Constants.TRANSFER_STATE_REVOKE);

                creditTransferMapper.updateByPrimaryKey(creditTransfer);

                //4.根据这个债权标,找到其下面的所有收款计划,修改转让状态为正常,  bidId, 转让人id, 转让状态
                paymentScheduleDetailService.batchUpdateTransferStateByBidIdAndToLoginInfoId
                        (detail.getBidId(), creditTransfer.getTransFrom().getId(), PaymentScheduleDetail.TRANSFER_STATE_NORMAL);
            }


        }

    }

    @Override
    public PageInfo queryForSubscribePage(CreditTransferQueryObject qo) {
        PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
        List list = creditTransferMapper.ListForSubscribePage(qo);
        return new PageInfo(list);
    }
}
